<?php
require_once('libs/Smarty.class.php');

/**
 * Wraps the Smarty class to simplify operation and provides additional functions
 * registers plugings provided by Clare
 *
 */
class MySmarty extends Smarty {
	public $DesignTimeLeftDelimiter = '{#';
	public $DesignTimeRightDelimiter = '#}';
	public $DummyDesignTimeLeftDelimiter = '(|';
	public $DummyDesignTimeRightDelimiter = '|)';
	public $ParseTimeLeftDelimiter = '<!--{';
	public $ParseTimeRightDelimiter = '}-->';
   function __construct()
   {
        $this->Smarty();
		$path = ereg_replace("MySmarty.class.php","",__FILE__);
		$subpath = substr($path,0,strlen($path)-5);
		$this->config_dir = $path."config";
		$this->cache_dir = $path."cache";
		$this->compile_dir = $path."template_c";
		$path = $_SERVER['SCRIPT_FILENAME'];
		$position = strrpos($path,"/");
		$path = substr($path,0,$position);
		$this->template_dir = $path;

        $this->caching = 0;
        $this->force_compile = true;
        $this->compile_check = true;
        
        //change the delimiters
        $this->left_delimiter = $this->ParseTimeLeftDelimiter;
        $this->right_delimiter = $this->ParseTimeRightDelimiter;
        
        SmartyPlugin_resouce_fileRel2Php::Register($this);
        SmartyPlugin_resouce_str::Register($this);
        SmartyPlugin_prefilter_rewriteDesignTimeDelimiter::Register($this, 
	        $this->DesignTimeLeftDelimiter, $this->DesignTimeRightDelimiter, 
	        $this->ParseTimeLeftDelimiter, $this->ParseTimeRightDelimiter,
	        $this->DummyDesignTimeLeftDelimiter, $this->DummyDesignTimeRightDelimiter); 
	    SmartyPlugin_prefilter_removeUTF8BOM::Register($this);
	    SmartyPlugin_modifier_utf8trunc::Register($this);
	    SmartyPlugin_modifier_plainHTML::Register($this);
   }
}

/**
 * Smarty plugin
 * ------------------------------------------------------------- 
 * File:     
 * Type:     resource
 * Name:     fileRel2Php
 * Purpose:  Fetches templates specified by a relative path to the excution PHP script
 * -------------------------------------------------------------
 */
class SmartyPlugin_resouce_fileRel2Php
{
	const PluginName = 'fileRel2Php';
	public static function Register($smarty)
	{
		//register resources
        //callback: array("className","StaticMethodName")
        $smarty->register_resource(self::PluginName , array(
        	array(__CLASS__,'GetSource'),
        	array(__CLASS__,'GetTimestamp'),
        	array(__CLASS__,'IsSecure'),
        	array(__CLASS__,'IsTrusted')
        ));
	}

	public static function GetSource($tpl_name, &$tpl_source, $smarty)
	{
		//2006-08-01 18:00:34 GMT+0800 Arrix
		throw 'fileRel2Php resource is not supported any more! Because it does not uniquely identify a template source causing compilation and cache problem. Use file: instead';
	    $path = dirname($_SERVER['SCRIPT_FILENAME']).'/'.$tpl_name;
	    if (is_file($path)) {
	    	$tpl_source = file_get_contents($path);
	    	return true;
	    } else {
	    	return false;
	    }
	}
	
	/**
	 * 
	 *
	 * @param string $tpl_name
	 * @param int ref $tpl_timestamp
	 * @param Smarty ref $smarty
	 * @return bool
	 */
	public static function GetTimestamp($tpl_name, &$tpl_timestamp, $smarty)
	{
	     $path = dirname($_SERVER['SCRIPT_FILENAME']).'/'.$tpl_name;
	    if (is_file($path)) {
	    	$tpl_timestamp = filemtime($path);
	    	return true;
	    } else {
	    	return false;
	    }
	}
	
	public static function IsSecure($tpl_name, $smarty)
	{
	    // assume all templates are secure
	    return true;
	}
	
	public static function IsTrusted($tpl_name, $smarty)
	{
	    // not used for templates
	    return true;
	}
}
/**
 * Smarty plugin
 * ------------------------------------------------------------- 
 * File:     
 * Type:     resource
 * Name:     str
 * Purpose:  Fetches templates specified by a string
 * -------------------------------------------------------------
 */
class SmartyPlugin_resouce_str
{
	const PluginName = 'str';
	public static function Register($smarty)
	{
		//register resources
        //callback: array("className","StaticMethodName")
        $smarty->register_resource(self::PluginName , array(
        	array(__CLASS__,'GetSource'),
        	array(__CLASS__,'GetTimestamp'),
        	array(__CLASS__,'IsSecure'),
        	array(__CLASS__,'IsTrusted')
        ));
	}

	public static function GetSource($tpl_name, &$tpl_source, $smarty)
	{
	    $tpl_source = $tpl_name;
		return true;
	}
	
	/**
	 * 
	 *
	 * @param string $tpl_name
	 * @param int ref $tpl_timestamp
	 * @param Smarty ref $smarty
	 * @return bool
	 */
	public static function GetTimestamp($tpl_name, &$tpl_timestamp, $smarty)
	{
	    return time();
	}
	
	public static function IsSecure($tpl_name, $smarty)
	{
	    // assume all templates are secure
	    return true;
	}
	
	public static function IsTrusted($tpl_name, $smarty)
	{
	    // not used for templates
	    return true;
	}
}
/**
 * Smarty plugin
 * ------------------------------------------------------------- 
 * File:     
 * Type:     prefilter
 * Name:     rewriteDesignTimeDelimiter
 * Purpose:  replaces design time delimiter with parse time delimiter
 * This plugin is designed to improve design time experience with Dreamweaver.
 * Dreamweaver will display Smarty tags which control logic(e.g. {if}) and the preview looks scratchy.
 * Some solve this problem by changing Smarty delimiters into HTML comment tags(<!--{ }-->),
 * but variable tags (e.g. {$name}) are then not displayed.
 * 
 * The best way is to make Dreamweaver display variable tags while hiding controlling tags.
 * This can be achieved by setting the Smarty delimiters to HTML comment tags 
 * and introducing new design time delimiters (e.g ({$name}))
 * 
 * We refer to delimiters that Smarty actually uses for compiling as parse time delimiters.
 * Then we can write in template controlling tags with parse time delimiters 
 * which are set to HTML comment and will not be displayed. 
 * We write variable tags with newly introduced design time delimiters which are visible in Dreamweaver page preview.
 * 
 * If a Smarty tag is too long, it may enlarge your HTML table cell thus breaking the layout.
 * We can write with parse time delimiters in the cell(<!--{ }-->) for data assignment and dummy delimiters
 * to help design(Dreamweaver does not dispaly html comments). Content in the dummy delimiters will be removed by the filter. 
 * The purpose of dummy delimiters is merely to help design.
 * 
 * The prefilter is responsible for rewriting design time delimiters into parse time delimiters.
 * 
 * The prefilter is also useful when delimiters in the template are different with those in Smarty setting
 * 
 * @example  
 * <table border="1">
 * <!--{section name=sec1 loop=$contactList}-->
 * <tr>
 * <td>id:({$contactList[sec1].id})</td>
 * <td>name:({$contactList[sec1].name})</td>
 * </tr>
 * <!--{/section}-->
 * -------------------------------------------------------------
 */
class SmartyPlugin_prefilter_rewriteDesignTimeDelimiter
{
	const PluginName = 'rewriteDesignTimeDelimiter';
	public static  $DesignTimeLeftDelimiter = '';
	public static  $DesignTimeRightDelimiter = '';
	public static  $DummyDesignTimeLeftDelimiter = '';
	public static  $DummyDesignTimeRightDelimiter = '';
	public static  $ParseTimeLeftDelimiter = '';
	public static  $ParseTimeRightDelimiter = '';
	
	/**
	 * Enter description here...
	 *
	 * @param Smarty $smarty	
	 * @param string $designLeft	DesignTimeLeftDelimiter
	 * @param string $designRight	DesignTimeRightDelimiter
	 * @param string $parseLeft	$ParTimeLeftDelimiter
	 * @param string $parseRight	ParseTimeRightDelimiter
	 * @param string $dummyLeft	optional
	 * @param string $dummyRight	optional
	 * @return  void
	 */
	
	public static function Register($smarty, $designLeft, $designRight, $parseLeft, $parseRight, $dummyLeft=null, $dummyRight=null)
	{
		self::$DesignTimeLeftDelimiter = $designLeft;
		self::$DesignTimeRightDelimiter = $designRight;
		self::$DummyDesignTimeLeftDelimiter = $dummyLeft;
		self::$DummyDesignTimeRightDelimiter = $dummyRight;
		self::$ParseTimeLeftDelimiter = $parseLeft;
		self::$ParseTimeRightDelimiter = $parseRight;
        //callback: array("className","StaticMethodName")
        /* @var $smarty MySmarty */
        $smarty->register_prefilter(array(__CLASS__, 'RewriteDelimiter'));
	}

	public static function RewriteDelimiter($source, $smarty)
	{
		/* @var $smarty MySmarty */
		//replace design time delimiters with parse time delimiterse
		$source = str_replace(self::$DesignTimeLeftDelimiter, self::$ParseTimeLeftDelimiter, $source);
		$source = str_replace(self::$DesignTimeRightDelimiter, self::$ParseTimeRightDelimiter, $source);
		//remove dummy tags
		if (!empty(self::$DummyDesignTimeLeftDelimiter) && !empty(self::$DummyDesignTimeRightDelimiter)) {
			$regExp = '/'.preg_quote(self::$DummyDesignTimeLeftDelimiter, '/').'.*?'.preg_quote(self::$DummyDesignTimeRightDelimiter, '/').'/s';
			$source = preg_replace($regExp, '', $source);
		}
		
		return $source;
	}
}

/**
 * Smarty prefilter, removes the BOM(byte order mark) of the template source to avoid HTML DOCTYPE corruption.
 * Smarty outputs a blank line before the acutual content. BOM after a blank line corrupts the HTML DOCTYPE
 *
 */
class SmartyPlugin_prefilter_removeUTF8BOM
{
	const PluginName = 'removeUTF8BOM';
	
	public static function Register($smarty)
	{
        //callback: array("className","StaticMethodName")
       $smarty->register_prefilter(array(__CLASS__, 'RemoveUTF8BOM'));
	}

	public static function RemoveUTF8BOM($source, $smarty)
	{
		$first3bytes = substr($source, 0,3);
		$bom = "﻿";
		if ($first3bytes === $bom) {
			$source = substr($source,3);
		}
		return $source;
	}
}

class SmartyPlugin_modifier_utf8trunc {
	const PluginName = 'utf8trunc';
	public static function Register($smarty)
	{
        //callback: array("className","StaticMethodName")
       $smarty->register_modifier(self::PluginName, array(__CLASS__, 'utf8Truncate'));
	}

	public static function utf8Truncate($string, $width = 80, $etc = '…',
                                  $break_words = false, $middle = false)
	{
	    if ($width == 0)
	        return '';
	
	    if (mb_strwidth($string, 'utf-8') > $width) {
	        $length -= mb_strwidth($etc, 'utf-8');
	        if (!$break_words && !$middle) {
	            $string = preg_replace('/\s+?(\S+)?$/u', '', mb_strimwidth($string, 0, $width+1, '', 'utf-8'));
	        }
	        if(!$middle) {
	            return mb_strimwidth($string, 0, $width, '', 'utf-8').$etc;
	        } else {
	            return mb_strimwidth($string, 0, $width/2, '', 'utf-8') . $etc . mb_strimwidth($string, -$width/2, '', 'utf-8');
	        }
	    } else {
	        return $string;
	    }
	}
}

class SmartyPlugin_modifier_plainHTML {
	const PluginName = 'plain';
	public static function Register($smarty)
	{
        //callback: array("className","StaticMethodName")
       $smarty->register_modifier(self::PluginName, array(__CLASS__, 'plainHTML'));
	}

	public static function plainHTML($string, $width = -1, $etc = '…')
	{
	    $s = str_replace("\r", "\n", $string);
	    $s = str_replace("\t", '    ', $s);
	    if ($width > 0) {
	    	$s = SmartyPlugin_modifier_utf8trunc::utf8Truncate($s, $width, $etc, true);
	    }
	    $s = str_replace("\n", '-@####@-', $s);
	    $s = str_replace(" ", '-@#++#@-', $s);
		$s = htmlentities($s, ENT_COMPAT, 'utf-8');
		$s = str_replace('-@####@-', '<br/>', $s);
		$s = str_replace('-@#++#@-', '&nbsp;', $s);
		return $s;
	}
}

?>